package com.kkh.tp;

import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.UnknownHostException;
import java.nio.ByteBuffer;
import java.nio.channels.SelectableChannel;
import java.nio.channels.SocketChannel;

import android.content.Context;
import android.os.Handler;
import android.os.Message;

public class SCChannel {
//	public static final int MSG_CONNECTED=1;
//	public static final int MSG_READ=2;
//	public static final int MSG_DISCONNECTED = 3;
//	public static final int MSG_ACCEPTED = 4;
//	
//	public static final int STATUS_DISCONNECTED=0;
//	public static final int STATUS_CONNECTED=1;
//	public static final int STATUS_ACCEPTED=2;
	
	private byte[] writePacket;
	
	int mStatus;
	private Context mContext;
	private Handler mHandler;
	
	int mType; //0:tcp, 1:udp
	
	public int channelId;
	public boolean used;
	ISCChannel mCallback;
	ISCServerChannel mServerCallback;
	
	InetAddress remoteIp;
	public InetSocketAddress socketAddr;
	public InetSocketAddress remoteAddr;
	
	//public SocketChannel socketChannel;
	public SelectableChannel socketChannel; 
	
	int remotePort;
	SCTransport mTp;
	
	public SCChannel(SCTransport tp) {
		mType = 0;
		mTp = tp;
		mContext = tp.getContext();
		init();
	}
	
	public SCChannel(SCTransport tp, int protocol) {
		mType = protocol;
		mTp = tp;
		mContext = tp.getContext();
		init();
	}
	
	
	
	void init() {
//		mHandler = new Handler() {
//			@Override
//			public void handleMessage(Message msg) {
//				// TODO Auto-generated method stub
//				super.handleMessage(msg);
//				
//				if(msg.what == MSG_CONNECTED) {
//					mStatus = STATUS_CONNECTED;
//					mCallback.OnStatusChanged(SCChannel.this, mStatus);
//				}
//				else if(msg.what == MSG_DISCONNECTED) {
//					mStatus = STATUS_DISCONNECTED;
//					mCallback.OnStatusChanged(SCChannel.this, mStatus);
//				}
//				else if(msg.what == MSG_READ) {
//					
//					mCallback.OnReceive(SCChannel.this, (byte[])msg.obj, msg.arg1);
//				}
//				else if(msg.what == MSG_ACCEPTED) {
//					mStatus = STATUS_ACCEPTED;
//					mCallback.OnStatusChanged(SCChannel.this, mStatus);
//					mStatus = STATUS_CONNECTED;
//				}
//			}};
	}
	
	
	
	public int requestConnect(String ip, int port) {
		try {
			remoteIp = InetAddress.getByName(ip);
		} catch (UnknownHostException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		remotePort = port;
		//TPCmd cmd = new TPCmd(TPCmd.CMD_CONNECT, channelId, port, remoteIp);
		InetSocketAddress remoteaddr = new InetSocketAddress(remoteIp, remotePort);
		TPCmd cmd = new TPCmd(TPCmd.CMD_CONNECT, this, remoteaddr);
		mTp.postCmd(cmd);
		mStatus = SCTransport.STATUS_CONNECTING;
		return 0;
	}
	
	
	
	public void requestClose() {
		TPCmd cmd = new TPCmd(TPCmd.CMD_CLOSE, 0, 0, this);
		mTp.postCmd(cmd);
		mStatus = SCTransport.STATUS_DISCONNECTED;
	}
	
	public int requestListen(int port) {
		TPCmd cmd = new TPCmd(TPCmd.CMD_LISTEN, port, 0, this);
		mTp.postCmd(cmd);
		return 0;
	}
	
	public int requestWrite(byte[] packet) {
		
		
		if(mType == 0 && mStatus != SCTransport.STATUS_CONNECTED)
			return -1;
		
		TPCmd cmd = new TPCmd(TPCmd.CMD_WRITE, packet.length, 0, this, packet);
		mTp.postCmd(cmd);
		return 0;
	}
	
	public void requestBind(int port) {
		TPCmd cmd = new TPCmd(TPCmd.CMD_BIND, port, 0, this);
		mTp.postCmd(cmd);
	}
	

	public void setOnListener(ISCChannel cb) {
		mCallback = cb;
	}
	
	public void setOnServerListener(ISCServerChannel cb) {
		mServerCallback = cb;
	}
	
	public int getStatus() {
		return mStatus;
	}
	
	public void sendEvent(int event) {
		mHandler.sendEmptyMessage(event);
	}
	
	public void sendEvent(int event, byte[] buf, int cnt) {
		Message msg = new Message();
		msg.what = event;
		msg.arg1 = cnt;
		msg.obj = buf;
		mHandler.sendMessage(msg);
	}
	
	public void sendEvent(int event, Object obj) {
		Message msg = new Message();
		msg.what = event;
		msg.obj = obj;
		mHandler.sendMessage(msg);
	}
	
	public byte[] getWritePacket() {

			byte[] ret = writePacket;
			return ret;

	}
	
	void _procMsgConnect() {
		mStatus = SCTransport.STATUS_CONNECTED;
		if(mCallback != null) 
			mCallback.OnSCStatusChanged(this, mStatus);
	}
	
	void _procMsgDisconnect() {
		mStatus = SCTransport.STATUS_DISCONNECTED;
		if(mCallback != null) 
			mCallback.OnSCStatusChanged(this, mStatus);
	}
	
	void _procMsgReceive(byte[] data, int count) {
		if(mCallback != null) 
			mCallback.OnSCReceive(this, data, count);
	}
	
	void _procMsgAccept(SCChannel schannel, SCChannel childschannel) {
		
		if(mServerCallback != null) {
			mServerCallback.OnAccept(this, childschannel);
		}
	}
	
	public String getRemoteIp() {
		return remoteAddr.getAddress().getHostAddress();
	}
	
	public int getRemotePort() {
		return remoteAddr.getPort();
	}
	
	public int write(byte[] buf) {
		return write(buf, buf.length);
	}
	
	public int write(byte[] buf, int len) {
		int wcnt;
		SocketChannel sch = (SocketChannel)socketChannel;
		try {
			wcnt = sch.write(ByteBuffer.wrap(buf, 0, len));
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			wcnt = -100;
		}
		return wcnt;
	}
	
	public int read(byte[] buf) {
		int rdcnt;
		SocketChannel sch = (SocketChannel)socketChannel;
		ByteBuffer bytebuf = ByteBuffer.wrap(buf);
		try {
			rdcnt = sch.read(bytebuf);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			rdcnt = -100; 
		}
		
		return rdcnt;
	}
	
	
	

	protected boolean OnStatusChanged(int stauts) {
		return false;
	}
	
	protected boolean OnReceive(byte[] data) {
		return false;
	}
	
	protected boolean OnWrite() {
		return false;
	}
	
	protected SCChannel OnAccept(SocketChannel child) {
		return null;
	}
	
}

